const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

// 复用loader
const commonCssLoader = [
    // 替换 style-loader,将css打包到单独的css文件
    MiniCssExtractPlugin.loader,
    'css-loader',
    {
        // css兼容性处理
        // 还需在package.json 中定义browserlist
        loader:'postcss-loader',
        options:{
            ident:'postcss',
            plugins:()=>[require('postcss-preset-env')()]
        }
    }
]



/* 
缓存:
    babel缓存
        cacheDirectory:true
        --> 让第二次打包构建速度更快
    文件资源缓存
        hash: 每次webpack构建时会生成一个唯一的hash值。
            问题：js和css同时使用一个hash值。
                如果重新打包，会导致所有缓存失效。
        chunkhash：根据chunk生成的hash值。如果打包来源与同一个chunk，那么hash值就一样
            问题：js和css的hash值还是一样的
             因为css是在js中被引入的，所以同属于一个chunk
        contenthash：根据文件的内容生成hash值。不同文件hash值一定不一样
        --> 让代码上线运行缓存更好使用


*/

/* 
tree shaking    去除无用代码
    前提:1.必须使用ES6模块化    2.开启production环境
    作用:减少代码体积

    子package.json中配置
        "sideEffects":false        所有代码都没有副作用(都可以进行tree shaking)
            问题:可能会把css / @babel / polyfill (副作用)文件干掉
        "sideEffects":["*.css","*.less"]
*/


/* 
三、
通过js代码,让某个文件被单独打包成一个chunk
    1.import('./src/test.js') 动态导入语法(ES10语法):能将文件单独打包,返回一个Promise
    2.import(/*webpackChunkName:'test'*/'./test')
*/
module.exports = {
    // 单入口
    entry:'./src/index.js',
    // 多入口
    //一、 entry:{
    //     main:'./src/js/index.js',
    //     test:'./src/js/test.js'
    // },
    output:{
        filename:'js/[name].built.js',
        path:resolve(__dirname,'public')
    },
    /* 
    二、
    1.可以将node_modules中代码打包一个chunk最终输出
    2.自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独chunk
    */
   optimization:{
       splitChunks:{
           chunks:'all'
       }
   },
    module:{
        rules:[
            // eslint 语法检查配置
            // 在package.json中配置eslintConfig -->airbnb
            {
                test:/\.js$/,
                exclude:/node_modules/,
                // 优先执行
                enforce:'pre',
                loader:'eslint-loader',
                options:{
                    fix:true
                }
            },
            {
                // 每一个文件只会匹配一个loader
                // 注意:不能有两个位置处理同一种类型文件
                oneOf:[
                    {
                        test:/\.css$/,
                        use:[...commonCssLoader]
                    },
                    {
                        test:/\.less/,
                        use:[
                            ...commonCssLoader,
                            'less-loader'
                        ]
                    },
                    
                    {
                        // js 兼容性处理
                        // 依赖于 @babel/core 核心库
                        test:/\.js$/,
                        exclude:/node_modules/,
                        loader:'babel-loader',
                        options:{
                            preset:[
                                // 基础语法兼容
                                '@babel/preset-env',
                                // 按需加载 兼容高级语法
                                {
                                    useBuiltIns:'usage',
                                    corejs:{version:3},
                                    target:{
                                        chrome:'60',
                                        // ...
                                    }
                                }
                            ],
                            // 开启bable缓存
                            // 第二次构建时,会读取之前的缓存
                            cacheDirectory:true
                        }
                    },
                    {
                        // 图片处理
                        // 依赖于 file-loader
                        test:/\.(jpg|png|gif)/,
                        loader:'url-loader',
                        option:{
                            limit:8*1024,
                            name:'[hash:10].[ext]',
                            outputPath:'imgs',
                            esModule:false,
                        }
                    },
                    {
                        // 处理html中的图片资源
                        test:'\.html$',
                        test:'html-loader',
                    },
                    {
                        // 处理其他文件
                        exclude:/\.(js|css|less|html|jpg|png|gif)/,
                        loader:'file-loader',
                        options:{
                            outputPath:'media'
                        }
                    }
                ]
            }
            
        ]
    },
    plugins:[
        // 将css文件单独提取出来
        new MiniCssExtractPlugin({
            // 提取到指定文件
            filename:'css/built.css'
        }),
        // 压缩css文件
        new OptimizeCssAssetsWebpackPlugin(),
        // 自动生成html文件
        new HtmlWebpackPlugin({
            // 生成html文件的模板
            template:'./src/index.html',
            // html文件压缩
            minify:{
                // 清楚空格
                collapseWhitespace:true,
                // 清楚注释
                removeComments:true,
            }
        })
    ],
    // 生产模式默认开启js代码压缩
    mode:'production',
}